package core

import (
	"bytes"
	"fmt"
	"github.com/gin-gonic/gin"
	"golang.org/x/time/rate"
	"io"
	"mallgo/config"
	"mallgo/internal/common/response"
	logger2 "mallgo/logger"
	"mallgo/utils"
	"net/http"
	"reflect"
	"runtime/debug"
	"strings"
	"time"
)

var logger = logger2.GetLogger()

type AppServer struct {
	Debug  bool
	Config *config.Config
	Engine *gin.Engine
}

func NewServer(config *config.Config) *AppServer {
	gin.SetMode(gin.DebugMode)
	gin.DefaultWriter = io.Discard
	return &AppServer{
		Debug:  false,
		Config: config,
		Engine: gin.Default(),
	}
}

func (s *AppServer) Init(debug bool) {
	if debug { // 调试模式允许跨域请求 API
		s.Debug = debug
		logger.Info("Enabled debug mode")
	}
	s.Engine.Use(corsMiddleware())
	s.Engine.Use(staticResourceMiddleware())
	//s.Engine.Use(authorizeMiddleware(s, client))
	s.Engine.Use(parameterHandlerMiddleware())
	s.Engine.Use(errorHandler)
	// 添加静态资源访问
	s.Engine.Static("/static", s.Config.StaticDir)

	// 创建限流器：每秒 34 次请求，最大桶容量 100
	limiter := rate.NewLimiter(rate.Every(200*time.Millisecond), 5) //// 使用限流器作为中间件
	//// 中间件：限流
	s.Engine.Use(func(c *gin.Context) {
		if limiter.Allow() == false {
			fmt.Println("====Disallow======", time.Now())
			c.JSON(http.StatusTooManyRequests, response.Error(501, "请求过于频繁，请稍后再试"))
			c.Abort()
			return
		}
		fmt.Println("====Allow======", time.Now())
		c.Next()
	})
}

// 全局日期格式化函数，用于遍历结构体中的时间字段
func formatDateFields(c *gin.Context) {
	// 获取响应数据
	if c.Writer.Status() == 200 { // 确保是成功响应
		// 使用反射遍历结构体中的所有字段
		//formatTimeInStruct(data)
	}
	c.Next()
}

// 遍历结构体中的所有字段，如果是 time.Time 类型，进行格式化
func formatTimeInStruct(v interface{}) {
	val := reflect.ValueOf(v)

	// 确保是结构体类型
	if val.Kind() == reflect.Struct {
		// 遍历所有字段
		for i := 0; i < val.NumField(); i++ {
			field := val.Field(i)

			// 如果是时间类型字段，进行格式化
			if field.Kind() == reflect.Struct && field.Type() == reflect.TypeOf(time.Time{}) {
				// 格式化时间
				field.Set(reflect.ValueOf(time.Now().Format("2006-01-02 15:04:05")))
			}
		}
	}
}

func Run(s *AppServer) {
	// load system configs
	port := s.Config.Server.Port
	if port == "" {
		port = "8080"
	}
	s.Init(true)

	err := s.Engine.Run(":" + port)
	if err != nil {
		logger.Error("启动服务失败 ", err)
		return
	}
	logger.Info("Server is running on port " + port)
}

// 统一参数处理
func parameterHandlerMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		// GET 参数处理
		params := c.Request.URL.Query()
		for key, values := range params {
			for i, value := range values {
				params[key][i] = strings.TrimSpace(value)
			}
		}
		// update get parameters
		c.Request.URL.RawQuery = params.Encode()
		// skip file upload requests
		contentType := c.Request.Header.Get("Content-Type")
		if strings.Contains(contentType, "multipart/form-data") {
			c.Next()
			return
		}

		if strings.Contains(contentType, "application/json") {
			// process POST JSON request body
			bodyBytes, err := io.ReadAll(c.Request.Body)
			if err != nil {
				c.Next()
				return
			}

			// 还原请求体
			c.Request.Body = io.NopCloser(bytes.NewBuffer(bodyBytes))
			// 将请求体解析为 JSON
			var jsonData map[string]interface{}
			if err := c.ShouldBindJSON(&jsonData); err != nil {
				c.Next()
				return
			}

			// 对 JSON 数据中的字符串值去除两端空格
			trimJSONStrings(jsonData)
			// 更新请求体
			c.Request.Body = io.NopCloser(bytes.NewBufferString(utils.JsonEncode(jsonData)))
		}

		c.Next()
	}
}

// 全局异常处理
func errorHandler(c *gin.Context) {
	defer func() {
		if r := recover(); r != nil {
			logger.Errorf("Handler Panic: %v", r)
			debug.PrintStack()
			c.JSON(http.StatusBadRequest, response.Error(400, "服务器内部错误"))
			c.Abort()
		}
	}()
	//加载完 defer recover，继续后续接口调用
	c.Next()
}

// 跨域中间件设置
func corsMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		method := c.Request.Method
		origin := c.Request.Header.Get("Origin")
		if origin != "" {
			// 设置允许的请求源
			c.Header("Access-Control-Allow-Origin", origin)
			c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, UPDATE")
			//允许跨域设置可以返回其他子段，可以自定义字段
			c.Header("Access-Control-Allow-Headers", "Authorization, Content-Length, Content-Type, Chat-Token, Admin-Authorization")
			// 允许浏览器（客户端）可以解析的头部 （重要）
			c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers")
			//设置缓存时间
			c.Header("Access-Control-Max-Age", "172800")
			//允许客户端传递校验信息比如 cookie (重要)
			c.Header("Access-Control-Allow-Credentials", "true")
		}

		if method == http.MethodOptions {
			c.JSON(http.StatusOK, "ok!")
		}

		defer func() {
			if err := recover(); err != nil {
				logger.Info("Panic info is: %v", err)
			}
		}()

		c.Next()
	}
}

// 静态资源中间件
func staticResourceMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {

		url := c.Request.URL.String()
		// 拦截生成缩略图请求
		if strings.HasPrefix(url, "/static/") && strings.Contains(url, "?imageView2") {
			r := strings.SplitAfter(url, "imageView2")
			size := strings.Split(r[1], "/")
			if len(size) != 8 {
				c.String(http.StatusNotFound, "invalid thumb args")
				return
			}

			// 设置图片缓存有效期为一年 (365天)
			c.Header("Cache-Control", "max-age=31536000, public")
			// 直接输出图像数据流
			c.Abort() // 中断请求

		}
		c.Next()
	}
}

// 递归对 JSON 数据中的字符串值去除两端空格
func trimJSONStrings(data interface{}) {
	switch v := data.(type) {
	case map[string]interface{}:
		for key, value := range v {
			switch valueType := value.(type) {
			case string:
				v[key] = strings.TrimSpace(valueType)
			case map[string]interface{}, []interface{}:
				trimJSONStrings(value)
			}
		}
	case []interface{}:
		for i, value := range v {
			switch valueType := value.(type) {
			case string:
				v[i] = strings.TrimSpace(valueType)
			case map[string]interface{}, []interface{}:
				trimJSONStrings(value)
			}
		}
	}
}
